package com.cdz.service.impl;

import com.cdz.commen.R;
import com.cdz.domain.ChargingPileInfo;
import com.cdz.domain.Firmware;
import com.cdz.form.*;
import com.cdz.mapper.ChargingPileInfoMapper;
import com.cdz.mapper.OtaMapper;
import com.cdz.service.FirmwareRepository;
import com.cdz.service.OtaService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;

import static com.cdz.enums.ErrorEnum.*;


@Service
public class OtaServiceImpl implements OtaService {


    private static final int BLOCK_SIZE = 1026;
    @Resource
    private OtaMapper otaMapper;

    @Resource
    private ChargingPileInfoMapper chargingPileInfoMapper;

    private final FirmwareRepository firmwareRepository;

    public OtaServiceImpl(FirmwareRepository firmwareRepository) {
        this.firmwareRepository = firmwareRepository;
    }

    @Override
    public ResponseEntity<String> uploadAllFile(MultipartFile file) {
        try {
            Firmware firmware = new Firmware();
            firmware.setId(1);
            firmware.setFileName(file.getOriginalFilename());
            firmware.setFileData(file.getBytes());
            firmware.setUploadTime(LocalDateTime.now());
            firmwareRepository.save(firmware);
            otaMapper.setUpdate1();
            return ResponseEntity.ok("文件上传成功");
        } catch (IOException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("文件处理失败: " + e.getMessage());
        }
    }
    @Override
    public R<?> updateOneFile(OneDataForm oneDataForm) throws IOException {
        String chargingPileId = oneDataForm.getChargingPileId();
        MultipartFile file = oneDataForm.getFile();
        Timestamp updateTime =  new Timestamp(System.currentTimeMillis());
        ChargingPileInfo chargingPileInfo = new ChargingPileInfo();
        chargingPileInfo.setChargingPileId(chargingPileId);
        chargingPileInfo.setFileName(file.getOriginalFilename());
        chargingPileInfo.setFileData(file.getBytes());
        chargingPileInfo.setUpdateStatus(2);
        chargingPileInfo.setUpdateTime(updateTime);
        otaMapper.updateCPFile(chargingPileInfo);
        return R.ok();
    }

    @Override
    public R<?> getMaintenanceInfo() {
        // 初始化返回列表
        List<MaintenanceForm> maintenanceFormList = new ArrayList<>();
        // 获取充电桩列表
        List<ChargingPileInfo> chargingPileInfoList = chargingPileInfoMapper.getPiles();
        // 遍历充电桩列表，构造 OneDataForm 对象
        for (ChargingPileInfo chargingPileInfo : chargingPileInfoList) {
            MaintenanceForm maintenanceForm = new MaintenanceForm();
            maintenanceForm.setChargingPileId(chargingPileInfo.getChargingPileId());
            maintenanceForm.setFileName(chargingPileInfo.getFileName());
            maintenanceForm.setUploadTime(chargingPileInfo.getUpdateTime());
            maintenanceFormList.add(maintenanceForm);
        }
        // 返回成功结果
        return R.ok(maintenanceFormList);
    }

    @Override
    public R<?> setUpdate0(UpdateForm updateForm) {
        String chargingPileId = updateForm.getChargingPileId();
        int updateStatus = updateForm.getUpdateStatus();
        if (chargingPileId == null || chargingPileId.isEmpty()) {
            return R.fail(ID_NO_EXXIST_ERROR);
        }
        chargingPileInfoMapper.setUpdate0(chargingPileId, updateStatus);
        System.out.println("设置充电桩"+chargingPileId+"的updateStatus为："+updateStatus);
        return R.ok();
    }

    @Override
    public Iterable<Firmware> getBinAll() {
        return firmwareRepository.findAll();
    }

    @Override
    public R<DataForm> transferBin(String chargingPileId) {
        int updateStatus = otaMapper.getUpdateStatus(chargingPileId);
        byte[] fileData = getFileDataByUpdateStatus(updateStatus, chargingPileId);
        if (fileData == null || fileData.length == 0) {
            return R.fail(FILE_NO_EXIST_ERROR);
        }
        // 每 256 字节为一组数据块
        int chunkSize = 256;
        // 计算字节数
        int count = (int) Math.ceil((double) fileData.length);
        // 分割文件数据并计算 CRC16
        List<String> resultChunks = new ArrayList<>();
        int index = 0;
        while (index < fileData.length) {
            int end = Math.min(index + chunkSize, fileData.length);
            byte[] chunkData = Arrays.copyOfRange(fileData, index, end);
            // 计算 CRC16
            int crc = calculateCRC16_CCITT(chunkData);
            byte crcHigh = (byte) ((crc >> 8) & 0xFF);
            byte crcLow = (byte) (crc & 0xFF);
            // 转换数据块为十六进制字符串
            List<String> hexChunk = new ArrayList<>(chunkData.length + 2);
            for (byte b : chunkData) {
                hexChunk.add(String.format("%02X", b & 0xFF));
            }
            hexChunk.add(String.format("%02X", crcHigh));
            hexChunk.add(String.format("%02X", crcLow));
            // 使用逗号连接数据
            String chunkString = String.join(",", hexChunk);
            resultChunks.add(chunkString);

            index = end;
        }

        // 封装结果到 DataForm 对象
        DataForm dataForm = new DataForm(count, resultChunks);
        return R.ok(dataForm);
    }

    @Override
    public R<?> ifUpdate(String chargingPileId) {
        int updateStatus = otaMapper.getUpdateStatus(chargingPileId);
        if (updateStatus == 0) {
            return R.ok(false);
        }else {
            return R.ok(true);
        }
    }
    /**
     * 根据 updateStatus 获取 fileData
     */
    private byte[] getFileDataByUpdateStatus(int updateStatus, String chargingPileId) {
        switch (updateStatus) {
            case 1:
                Firmware firmware = otaMapper.selectBin();
                return firmware != null ? firmware.getFileData() : null;
            case 2:
                return otaMapper.selectOneBin(chargingPileId).getFileData();
            default:
                return null; // 或者抛出异常，表示无效的状态
        }
    }

    // 适配您的 CRC16 算法（CCITT，多项式 0x1021，初始值 0x0000）
    private int calculateCRC16_CCITT(byte[] data) {
        int crc = 0x0000;           // 初始值
        final int polynomial = 0x1021;  // 多项式
        for (byte b : data) {
            crc ^= (b & 0xFF) << 8;  // 高位先处理
            for (int i = 0; i < 8; i++) {
                if ((crc & 0x8000) != 0) {
                    crc = (crc << 1) ^ polynomial;
                } else {
                    crc <<= 1;
                }
                crc &= 0xFFFF;  // 保持16位
            }
        }
        return crc;
    }


}
